#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <ctime>
#include <memory>
#include <functional>
#include "Tcpserver.hpp"
#include "Session.hpp"
#include "Log.hpp"

const std::string HttpSep = "\r\n";
const std::string wwwroot = "./wwwroot";

class HttpRequest
{
public:
    HttpRequest() : _req_blank(HttpSep), _path(wwwroot) // 默认访问的路径
    {
    }
    bool GetLine(std::string &request, std::string &line)
    {
        auto pos = request.find(HttpSep);
        if (pos == std::string::npos)
            return false;
        line = request.substr(0, pos); // 按照换行符找到首行的结束位置并截取出来
        request.erase(0, pos + HttpSep.size());
        return true;
    }
    void Parse()
    {
        //解析url
        std::stringstream ss(_req_line);
        ss>>_method>>_url>>_version;
        //查找cookie
        std::string prefix="Cookie:";
        for(auto& line:_req_header)
        {
            std::string cookie;
            if(strncmp(line.c_str(),prefix.c_str(),prefix.size())==0)
            {
                cookie=line.substr(prefix.size());
                _cookies.emplace_back(cookie);
                break;
            }
        }

        //查看session_id
        prefix="sessionid=";
        for(auto&cookie :_cookies)
        {
            if(strncmp(cookie.c_str(),prefix.c_str(),prefix.size())==0)
            {
                _sessionid=cookie.substr(prefix.size());
            }
        }
    }
    std::string URL()
    {
        return _url;
    }
    std::string SessionId()
    {
        return _sessionid;
    }
    // 反序列化浏览器发送过来的请求
    bool Deserialize(std::string &request)
    {
        // 先从请求报文中获取到首行
        std::string _line;
        bool ret = GetLine(request, _line);
        if (!ret)
            return false;
        // 成功获取到请求报文的首行
        _req_line = _line;

        while (true)
        {
            bool ok = GetLine(request, _line);
            if (ok && _line.empty())
            {
                // 没有报头部分
                _req_content = request;
                break;
            }
            else if (ok && !_line.empty())
            {
                // 提取报头部分
                _req_header.push_back(_line);
            }
            else
            {
                break;
            }
        }
        return true;
    }

private:
    std::string _req_line;                // 首行
    std::vector<std::string> _req_header; // 报头
    std::string _req_blank;               // 空行
    std::string _req_content;             // 请求内容

    // 解析之后获得的内容
    std::string _version;              // http版本
    std::string _url;                  // 浏览器要访问的资源
    std::string _method;                // 请求方法get/post
    std::string _path;                 // 请求资源所在的路径
    std::string _suffix;               // 请求资源的后缀，决定给应答报文中添加Content-Type属性
    std::vector<std::string> _cookies; // 请求报文中的cookie属性,Set-Cookie
    std::string _sessionid;            // 请求报文将来将来要携带上自己的ssessionid信息
};

const std::string BlankSep = " ";   // 空格
const std::string LineSep = "\r\n"; // 行分隔符
// 应答报文
class HttpResponse
{
public:
    HttpResponse()
        : _http_version("http/1.0"), _status_code(200), _status_code_desc("OK"), _resp_blank(LineSep)
    {
    }
    void SetCode(int code)
    {
        _status_code = code;
    }
    void SetDesc(const std::string &desc)
    {
        _status_code_desc = desc;
    }
    // 添加正文
    void AddContent(const std::string &content)
    {
        _resp_content = content;
    }
    // 添加报头属性
    void AddHeader(const std::string &header)
    {
        _resp_header.push_back(header);
    }

    void MakeStatusLine()
    {
        _status_line = _http_version + BlankSep + std::to_string(_status_code) + BlankSep + _status_code_desc;
    }
    // 序列化
    std::string Serialize()
    {
        // 首先构建好状态行
        MakeStatusLine();
        // 然后加上报头本部分和正文部分
        std::string response_str = _status_line;
        for (auto &header : _resp_header)
        {
            response_str += header;
        }
        response_str += _resp_blank;
        response_str += _resp_content;
    }

private:
    std::string _status_line;              // 状态行
    std::vector<std::string> _resp_header; // 应答报头
    std::string _resp_blank;               // 空行
    std::string _resp_content;             // 正文部分

    // 解析之前的内容，也就是序列化之前的内容
    std::string _http_version;     // http版本
    int _status_code;              // 状态码
    std::string _status_code_desc; // 状态码描述信息
};

class Http
{
public:
    Http(uint16_t port)
    {
        _tsvr=std::make_unique<TcpServer>(port,
        bind(&Http::HandleHttp,this,std::placeholders::_1));
        _tsvr->Init();
        _session_manager=std::make_unique<SessionManager>();
    }
    std::string ProveCookieWrite()
    {
        return "Set-Cookie: username=zhangsan";
    }
    std::string ProveTimeout()
    {
        return "Set-Cookie: username=zhangsan; expires"+" ";//让cookie一分钟后会过期
    }
    std::string Path()
    {
        return "Set-Cookie: username=zhangsan; path=/a/b"
    }
    std::string ProveSessionId(const std::string& sessionId)
    {
        return "Set-Cookie: sessionid="+sessionId+";";
    }
    std::string HandleHttp(std::string request)
    {
        HttpRequest req;
        HttpResponse resp;
        req.Deserialize(request);
        req.Parse();

        static int number=0;
        if(req.URL()=="/login")
        {
            std::string sessionid=req.SessionId();
            if(sessionid.empty())//说明历史没有登陆过
            {
                std::string user="user-"+std::to_string(number++);
                //为用户构建session对象
                session_ptr s=std::make_shared<Session>(user,"login");

                //添加用户信息,同时为该session生成一个唯一的sessionid
                //将该sessionid添加到报头中，返回给用户
                std::string resp_sessionid=_session_manager->Addsession(s);

                lg.LogMessage(Debug,"%s 被添加,sessionid是: %s\n",user.c_str(),resp_sessionid);
                //返回给用户，将sessionid写入到报头中
                resp.AddHeader(ProveSessionId(resp_sessionid));
            }
        }
        else
        {
            std::string sessionid=req.
        }
    }

private:
    std::unique_ptr<TcpServer> _tsvr;
    std::unique_ptr<SessionManager> _session_manager;
};